#include "InternalCommands.h"
#include "MyShellGlobalVariables.h"
#include "MyShellAssistFunctions.h"
#include "ResourceManager.h"
#include "MyTextFileReaderAndWriterInterface.h"
#include "JParserNamespace.h"
#include "JNode.h"
#include "JParser.h"
#include "MyShellLexicalAnalyzer.h"
#include "MyShellParser.h"
#include "MyShellException.h"
#include "Executor.h"

#include <iostream>
#include <unordered_map>
#include <exception>
#include <unistd.h>

MY_SHELL_NAMESPACE_BEGIN
// 内部命令exit
void myExit(const std::vector<std::string>& splited_command)
{
    // 控制是否退出mysh
    bool if_exit = true;
    // 控制是否设定了新的退出状态
    bool if_new_exit_status = false;
    // 新的退出状态
    int new_exit_status = 0;
    if (splited_command.size() == 2)
    {
        // 帮助文档
        if (splited_command[1] == "--help")
        {
            std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
            std::cerr << "  " << "退出mysh" << std::endl;
            std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
            std::cerr << "  " << "exit [选项|参数]" << std::endl;
            std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
            std::cerr << "  " << "--help" << std::endl;
            std::cerr << "    " << "输出帮助文档" << std::endl;
            std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
            std::cerr << "  " << "32位自然数" << std::endl;
            std::cerr << "    " << "指定mysh以什么状态退出" << std::endl;
            return;
        }
        // 获取参数中的退出状态
        else
        {
            try
            {
                new_exit_status = std::stoul(splited_command[1]);
                if_new_exit_status = true;
            }
            catch(const std::exception& e)
            {
                std::cerr << "\033[31m" << "参数错误，可使用\"exit --help\"查看帮助文档" << "\033[0m" << '\n';
                if_exit = false;
            }
        }
    }
    // 参数过多
    else if (splited_command.size() > 2)
    {
        std::cerr << "\033[31m" << "参数过多，可使用\"exit --help\"查看帮助文档" << "\033[0m" << std::endl;
        if_exit = false;
    }
    // 确定退出
    if (if_exit)
    {
        // 更新mysh的退出状态
        if (if_new_exit_status) mysh::exit_status = new_exit_status;
        // 是否退出主循环设为真
        mysh::if_break = true;
        // 输出退出语句
        std::cerr << "\033[93m" << mysh::exit_statement[rand() % mysh::exit_statement.size()] << "\033[0m" << std::endl;
        // 将命令历史记录保存进命令历史记录文件中
        textfilerw::TextFileReaderAndWriter tfrw = textfilerw::TextFileReaderAndWriter();
        tfrw.write(mysh::join(mysh::mysh_history_commands), mysh::mysh_history_file_name);
        // 将新别名(或变量)保存今配置文件中
        std::unordered_map<std::string, myjson::JNode> new_alias = std::unordered_map<std::string, myjson::JNode>();
        for (std::unordered_map<std::string, std::string>::iterator iter = mysh::alias.begin(); iter != mysh::alias.end(); iter++)
        {
            new_alias[iter->first] = myjson::JNode(iter->second);
        }
        mysh::my_shell_configurations.updateObjectKeyValue("alias", new_alias);
        textfilerw::TextFileReaderAndWriter tfrw2 = textfilerw::TextFileReaderAndWriter();
        tfrw2.write(mysh::my_shell_configurations.toFormatJSONText(), mysh::myshrc_file_name);
        // 阻塞2s
        sleep(2);
    }
}

// 内部命令change-skip，用于修改跳过字符
void myChangeSkip(const std::vector<std::string>& splited_command)
{
    if (splited_command.size() > 2)
    {
        std::cerr << "\033[31m" << "当前指令仅需1个参数" << "\033[0m" << std::endl;
    }
    else if (splited_command.size() <= 1)
    {
        std::cerr << "\033[31m" << "当前指令需要1个参数" << "\033[0m" << std::endl;
    }
    else
    {
        if (splited_command[1].size() != 1)
        {
            std::cerr << "\033[31m" << "参数应为单个字符" << "\033[0m" << std::endl;
        }
        else
        {
            mysh::default_skip_char = splited_command[1][0];
            std::cerr << "\033[32m" << "修改跳过字符成功！" << "\033[0m" << std::endl;
            std::cerr << "\033[32m" << "当前跳过字符为：\'" << mysh::default_skip_char << "\'" << "\033[0m" << std::endl;
            std::cerr.flush();
        }
    }
}

// 内部命令ls
void myLS(const std::vector<std::string>& splited_command)
{
    // 仅输入ls等同于ls -a，表示显示当前路径下的所有文件
    if (splited_command.size() == 1)
    {
        mysh::resource_manager->printCurrentAllFiles();
        return;
    }
    // 帮助文档
    if (splited_command.size() == 2 && splited_command[1] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "显示某目录下的内容" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "ls [[选项] [参数]...]..." << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "  " << "-l" << std::endl;
        std::cerr << "    " << "使用较长格式列出信息" << std::endl;
        std::cerr << "  " << "-a" << std::endl;
        std::cerr << "    " << "列出所有文件，包含隐藏文件" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "路径或子目录" << std::endl;
        std::cerr << "    " << "指定需要显示内容的目录" << std::endl;
        return;
    }
    // 可用选项
    static std::unordered_set<std::string> available_options = {
        "-l",  // 用较长格式列出信息
        "-a"   // 列出所有文件，包含隐藏文件
    };
    // 用于存储重组织命令
    std::unordered_map<std::string, std::vector<std::string>> organized_command = std::unordered_map<std::string, std::vector<std::string>>();
    // 当前选项
    std::string cur_option = std::string();
    // splited_command数组中的前一个值是选项
    bool if_pre_option = true;
    // 重组织命令
    for (std::int32_t i = 1; i < splited_command.size(); i++)
    {
        // splited_command当前值是选项
        if (splited_command[i][0] == '-')
        {
            // 前一个值是一个可用的选项，但当前值也是一个选项，则默认前一个选项的参数是当前路径
            if (if_pre_option && !cur_option.empty())
            {
                organized_command[cur_option].push_back(mysh::resource_manager->root_path.string());
            }
            // 当前值不在可用选项中
            if (!available_options.count(splited_command[i]))
            {
                if (splited_command[i] == "--help")
                {
                    std::cerr << "\033[31m" << "选项" << splited_command[i] << "仅可通过\"ls --help\"使用" << "\033[0m" << std::endl;
                }
                else
                {
                    std::cerr << "\033[31m" << "选项" << splited_command[i] << "不是可用选项，可使用\"ls --help\"查看帮助文档" << "\033[0m" << std::endl;
                }
                cur_option.clear();
            }
            // 当前选项可用，更新cur_option, 若之前没遇见这个选项，则在重组织命令unordered_map中对此选项进行初始化
            else
            {
                cur_option = splited_command[i];
                if (!organized_command.count(cur_option))
                {
                    organized_command[cur_option] = std::vector<std::string>();
                }
            }
            // 前一个值是选项
            if_pre_option = true;
        }
        else
        {
            // 当前选项为空
            if (cur_option.empty())
            {
                std::cerr << "\033[31m" << "参数" << splited_command[i] << "没有对应的选项，请检查" << "\033[0m" << std::endl;
            }
            // 选项不为空
            else 
            {
                // 若开头的字符不是斜杠，则认为当前的参数是当前路径下的文件名或目录名，将其补全后再加入重组织命令中，其他的直接加入
                std::string cur_arg = splited_command[i];
                if (cur_arg[0] != '/' && cur_arg[0] != '\\')
                {
                    cur_arg = std::string(getenv("PWD")) + "/" + cur_arg;
                }
                organized_command[cur_option].push_back(cur_arg);
            }
            // 前一个值不是选项
            if_pre_option = false;
        }
    }
    // 最后一个参数是选项且这个可用选项是新选项，则为这个选项添加默认参数
    if (if_pre_option && !cur_option.empty() && organized_command[cur_option].empty())
    {
        organized_command[cur_option].push_back(mysh::resource_manager->root_path.string());
    }
    // 根据重组织命令unordered_map执行命令
    for (std::unordered_map<std::string, std::vector<std::string>>::iterator iter = organized_command.begin(); iter != organized_command.end(); iter++)
    {
        // 列出所有文件，包括隐藏文件
        if (iter->first == "-a")
        {
            for (const std::string& path : iter->second)
            {
                mysh::ResourceManager* rm = new mysh::ResourceManager(path);
                rm->printCurrentAllFiles();
                delete rm;
                rm = nullptr;
            }
        }
        // 按较长格式列出文件信息
        else if (iter->first == "-l")
        {
            for (const std::string& path : iter->second)
            {
                mysh::ResourceManager* rm = new mysh::ResourceManager(path);
                rm->printCurrentFilesInList();
                delete rm;
                rm = nullptr;
            }
        }
    }
}

// 内部命令cd
void myCD(const std::vector<std::string>& splited_command)
{
    // 用于存储需要切换至的下一个工作路径
    std::string next_path = std::string();
    if (splited_command.size() == 2)
    {
        // 帮助文档
        if (splited_command[1] == "--help")
        {
            std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
            std::cerr << "  " << "将工作目录切换至指定目录" << std::endl;
            std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
            std::cerr << "  " << "cd <选项|参数>" << std::endl;
            std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
            std::cerr << "  " << "--help" << std::endl;
            std::cerr << "    " << "输出帮助文档" << std::endl;
            std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
            std::cerr << "  " << "路径或目录" << std::endl;
            std::cerr << "    " << "指定需要切换到的路径或目录" << std::endl;
            std::cerr << "  " << "特殊路径或目录" << std::endl;
            std::cerr << "    " << "(1) \".\": 当前目录" << std::endl;
            std::cerr << "    " << "(2) \"..\": 当前目录的父目录" << std::endl;
            std::cerr << "    " << "(3) \"~\": 家目录的路径" << std::endl;
            std::cerr << "    " << "(4) \"-\": 上一次访问的目录的路径" << std::endl;
            return;
        }
        // 参数为特殊路径或目录所指定的字符，则通过unique_path展开特殊路径或目录
        if (splited_command[1].size() == 1 && mysh::unique_path.count(splited_command[1][0]))
        {
            next_path = mysh::unique_path[splited_command[1][0]];
        }
        // 特殊路径".."的转换：利用资源管理器获取当前工作路径的父路径
        else if (splited_command[1] == "..")
        {
            next_path = mysh::resource_manager->root_path.parent_path().string();
        }
        // 其他情况
        else
        {
            // 路径参数的开头字符为斜杠，则将该参数直接赋值给next_path
            if (splited_command[1][0] == '/' || splited_command[1][0] == '\\')
            {
                next_path = splited_command[1];
            }
            // 路径参数开头字符不是斜杠，则认为该参数指的是当前工作路径下的子目录
            else
            {
                // 是否找到当前路径下的同名文件夹
                bool if_have_folder = false;
                // 当前参数
                std::string cur_splited_command = splited_command[1];
                // 从资源管理器中的cur_folders数组中查找
                for (std::int32_t i = 0; i < mysh::resource_manager->cur_folders.size(); i++)
                {
                    // 当前查找到的文件夹
                    std::string cur_resource_manager_folder = mysh::resource_manager->cur_folders[i];
                    // 去除cur_resource_manager_folder及cur_splited_command末尾的斜杠
                    if (cur_resource_manager_folder.back() == '/' || cur_resource_manager_folder.back() == '\\')
                    {
                        cur_resource_manager_folder.pop_back();
                    }
                    if (cur_splited_command.back() == '/' || cur_splited_command.back() == '\\')
                    {
                        cur_splited_command.pop_back();
                    }
                    // 当前查找到的文件夹与参数同名，则将该参数补全并退出查找
                    if (cur_splited_command == cur_resource_manager_folder)
                    {
                        if_have_folder = true;
                        next_path = mysh::resource_manager->root_path.string();
                        if (next_path.back() != '/') next_path += "/";
                        next_path += cur_splited_command;
                        break;
                    }
                }
                // 若没找到同名文件夹，则尝试从资源管理器中的cur_others数组中查找，查找思路与上一个循环一样，不再赘述
                if (!if_have_folder)
                {
                    for (std::int32_t i = 0; i < mysh::resource_manager->cur_others.size(); i++)
                    {
                        std::string cur_resource_manager_other = mysh::resource_manager->cur_others[i];
                        if (cur_resource_manager_other.back() == '/' || cur_resource_manager_other.back() == '\\')
                        {
                            cur_resource_manager_other.pop_back();
                        }
                        if (cur_splited_command.back() == '/' || cur_splited_command.back() == '\\')
                        {
                            cur_splited_command.pop_back();
                        }
                        if (cur_splited_command == cur_resource_manager_other)
                        {
                            if_have_folder = true;
                            next_path = mysh::resource_manager->root_path.string();
                            if (next_path.back() != '/') next_path += "/";
                            next_path += cur_splited_command;
                            break;
                        }
                    }
                }
                // 仍然没找到，则报告错误并退出
                if (!if_have_folder)
                {
                    std::cerr << "\033[31m" << "当前路径下不存在目录：\"" << splited_command[1] << "\"" << "\033[0m" << std::endl;
                    return;
                }
            }
        }
    }
    // 有下一个路径参数
    if (!next_path.empty())
    {
        // 前工作路径赋值为当前路径
        std::string pre_path = mysh::resource_manager->root_path.string();
        // 尝试通过changeRootPath函数修改资源管理器的路径
        // 修改工作路径成功
        if (mysh::resource_manager->changeRootPath(next_path))
        {
            // 修改环境变量PWD
            setenv("PWD", next_path.c_str(), 1);
            // 修改工作路径
            chdir(mysh::resource_manager->root_path.string().c_str());
            // 修改特殊路径中的‘-’路径，表示上一个工作路径
            mysh::unique_path['-'] = pre_path;
            // 修改特殊路径中的‘.’路径，表示当前工作路径
            mysh::unique_path['.'] = next_path;
            std::cerr << "\033[32m" << "修改工作目录成功！" << "\033[0m" << std::endl;
            std::cerr << "\033[32m" << "当前工作目录为：\"" << next_path << "\"" << "\033[0m" << std::endl;
            std::cerr.flush();
        }
        // 修改工作路径失败
        else
        {
            std::cerr << "\033[31m" << "路径不存在或不是一个目录: \"" << next_path << "\"" << "\033[0m" << std::endl;
        }
    }
    // 参数数量过多或过少
    else
    {
        std::cerr << "\033[31m" << "当前似乎未指定单个路径或目录，可通过\"cd --help\"查看帮助文档" << "\033[0m" << std::endl;
    }
}


// 内部命令alias子命令show
void myAliasShow(const std::vector<std::string>& splited_command)
{
    // 光输入alias show表示输出所有别名（或变量）
    if (splited_command.size() < 3)
    {
        std::cerr << "\033[32m" << "当前的所有别名(或变量)为：" << "\033[0m" << std::endl;
        for (std::unordered_map<std::string, std::string>::iterator iter = mysh::alias.begin(); iter != mysh::alias.end(); iter++)
        {
            std::cerr << "  " << iter->first << " = " << iter->second << std::endl;
        }
    }
    // alias show的帮助文档
    else if (splited_command.size() == 3 && splited_command[2] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "展示别名(或变量)" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "alias show [选项|{参数}...]" << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "用大括号括起来的别名(或变量)名称" << std::endl;
        std::cerr << "    " << "指定想展示的别名(或变量)" << std::endl;
    }
    // alias show有其他参数
    else
    {
        // 逐个解析参数，若合法，则输出这个参数对应的值
        for (std::int32_t i = 2; i < splited_command.size(); i++)
        {
            // 合法的参数应该被{}括起来
            if (splited_command[i].size() <= 2 || splited_command[i][0] != '{' || splited_command[i].back() != '}')
            {
                std::cerr << "\033[31m" << "参数\"" << splited_command[i] << "\"错误，可通过\"alias show --help查看帮助文档\"" << "\033[0m" << std::endl;
                continue;
            }
            // 当前合法参数
            std::string cur_alias = splited_command[i];
            // 去除大括号
            cur_alias.pop_back();
            cur_alias.erase(0, 1);
            // 存在这个别名（或变量）则输出其值
            if (mysh::alias.count(cur_alias))
            {
                std::cerr << "\033[32m" << cur_alias << " = " << mysh::alias[cur_alias] << "\033[0m" << std::endl;
            }
            // 否则报告错误
            else
            {
                std::cerr << "\033[31m" << "当前无此别名(或变量): " << cur_alias << "\033[0m" << std::endl;
            }
        }
    }
}

// 内部命令alias子命令delete
void myAliasDelete(const std::vector<std::string>& splited_command)
{
    // 光输入alias delete不执行任何操作
    if (splited_command.size() < 3)
    {
        std::cerr << "\033[31m" << "请输入需要删除的别名(或变量)，可通过\"alias delete --help\"查看帮助文档" << "\033[0m" << std::endl;
    }
    // 帮助文档
    else if (splited_command.size() == 3 && splited_command[2] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "删除别名(或变量)" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "alias delete [选项|{参数}...]" << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "用大括号括起来的别名(或变量)名称" << std::endl;
        std::cerr << "    " << "指定想删除的别名(或变量)" << std::endl;
    }
    // 删除别名(或变量)
    else
    {
        for (std::int32_t i = 2; i < splited_command.size(); i++)
        {
            // 合法的参数应该被{}括起来
            if (splited_command[i].size() <= 2 || splited_command[i][0] != '{' || splited_command[i].back() != '}')
            {
                std::cerr << "\033[31m" << "参数\"" << splited_command[i] << "\"错误，可通过\"alias delete --help查看帮助文档\"" << "\033[0m" << std::endl;
                continue;
            }
            // 当前合法参数
            std::string cur_alias = splited_command[i];
            // 去除大括号
            cur_alias.pop_back();
            cur_alias.erase(0, 1);
            // 存在这个别名(或变量)，则将其删除
            if (mysh::alias.count(cur_alias))
            {
                mysh::alias.erase(cur_alias);
                std::cerr << "\033[32m" << "别名(或变量)" << cur_alias << "已删除" << "\033[0m" << std::endl;
            }
            // 否则报告错误
            else
            {
                std::cerr << "\033[31m" << "当前无此别名(或变量): " << cur_alias << "\033[0m" << std::endl;
            }
        }
    }
}

// 内部命令alias
void myAlias(const std::vector<std::string>& splited_command)
{
    // 光输入alias不会有任何作用
    if (splited_command.size() < 2)
    {
        std::cerr << "\033[31m" << "请输入选项或子命令，可使用\"alias --help\"查看帮助文档" << "\033[0m" << std::endl;
        return;
    }
    // 帮助文档
    if (splited_command.size() == 2 && splited_command[1] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "展示或删除别名(或变量)" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "alias <选项|子命令>" << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "\033[32m" << "子命令：" << "\033[0m" << std::endl;
        std::cerr << "  " << "show" << std::endl;
        std::cerr << "    " << "展示别名(或变量)" << std::endl;
        std::cerr << "  " << "delete" << std::endl;
        std::cerr << "    " << "删除别名(或变量)" << std::endl;
        return;
    }
    // 子命令及其编号
    static std::unordered_map<std::string, std::int32_t> available_subcommands = {
        {"show", 0},
        {"delete", 1}
    };
    // 若splited_command的第二个值在可用子命令中，则根据这个子命令的编号进入对应的子命令函数继续执行
    if (available_subcommands.count(splited_command[1]))
    {
        std::int32_t subcommand_id = available_subcommands[splited_command[1]];
        switch(subcommand_id)
        {
        case 0:
            mysh::myAliasShow(splited_command);
            break;
        case 1:
            mysh::myAliasDelete(splited_command);
            break;
        }
    }
    // 第二个值不在可用子命令中
    else
    {
        std::cerr << "\033[31m" << "输入的选项或子命令尚不可用，可使用\"alias --help\"查看帮助文档" << "\033[0m" << std::endl;
    }
}

// 内部命令history
void myHistory(const std::vector<std::string>& splited_command)
{
    // 光输入history表示展示所有命令历史记录
    if (splited_command.size() < 2)
    {
        char cur_ch = 0;
        while (1)
        {
            std::cerr << "\033[32m" << "此命令将打印所有历史记录，请确认是否继续？[y/n]" << "\033[0m" << std::endl;
            // 输入y或Y则展示所有命令历史记录，输入n或N则退出
            if (read(STDIN_FILENO, &cur_ch, 1) == 1)
            {
                if (cur_ch == 'y' || cur_ch == 'Y')
                {
                    std::size_t n = mysh::mysh_history_commands.size();
                    for (std::int32_t i = 0; i < n; i++)
                    {
                        std::cerr << mysh::mysh_history_commands[i] << std::endl;
                        if (!isatty(STDOUT_FILENO))
                        {
                            std::cout << mysh::mysh_history_commands[i] << std::endl;
                        }
                    }
                    break;
                }
                else if (cur_ch == 'n' || cur_ch == 'N')
                {
                    break;
                }
                else
                {
                    std::cerr << "\033[31m" << "请输入y(yes)或n(no), 大小写都行" << std::endl;
                }
            }
        }
    }
    // 帮助文档
    else if (splited_command.size() == 2 && splited_command[1] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "操作或展示命令历史记录" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "history [选项]...[参数]..." << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "  " << "-r  --read" << std::endl;
        std::cerr << "    " << "读取历史记录文件，将其中的记录覆盖当前记录" << std::endl;
        std::cerr << "  " << "-w  --write" << std::endl;
        std::cerr << "    " << "将当前的历史记录写入历史记录文件" << std::endl;
        std::cerr << "  " << "-c  --clear" << std::endl;
        std::cerr << "    " << "将历史文件中的记录清空" << std::endl;
        std::cerr << "  " << "-s --start" << std::endl;
        std::cerr << "    " << "打印历史记录的起点索引, 接受一个32位整数作为参数" << std::endl;
        std::cerr << "  " << "-e --end" << std::endl;
        std::cerr << "    " << "打印历史记录的终点索引, 接受一个32位整数作为参数" << std::endl;
        std::cerr << "  " << "-n --num" << std::endl;
        std::cerr << "    " << "打印历史记录的记录数量, 接受一个32位整数作为参数" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "32位整数" << std::endl;
        std::cerr << "    " << "指定打印的起点索引或终点索引或记录数量" << std::endl;
    }
    // 带选项、参数的命令
    else
    {
        // 长选项转短选项
        static std::unordered_map<std::string, std::string> long_option_to_short_option = {
            {"--read", "-r"},   // 重读命令历史记录
            {"--write", "-w"},  // 覆写命令历史记录
            {"--clear", "-c"},  // 清空命令历史记录
            {"--start", "-s"},  // 展示命令历史记录的起点
            {"--end", "-e"},    // 展示命令历史记录的终点
            {"--num", "-n"}     // 展示命令历史记录的数量
        };
        // 短选项所需参数数量
        static std::unordered_map<std::string, std::int32_t> option_arg_count = {
            {"-r", 0},
            {"-w", 0},
            {"-c", 0},
            {"-s", 1},
            {"-e", 1},
            {"-n", 1}
        };
        // 短选项编号
        static std::unordered_map<std::string, std::int32_t> option_id = {
            {"-r", 0},
            {"-w", 1},
            {"-c", 2},
            {"-s", 3},
            {"-e", 4},
            {"-n", 5}
        };
        // 当前splited_command中的值是否为选项
        bool if_option = true;
        // 当前选项
        std::string cur_option = std::string();
        // 当前选项所需的参数个数
        std::int32_t arg_count = 0;
        // 每组-s、-e、-n对应的参数
        std::vector<std::vector<std::int32_t>> args = std::vector<std::vector<std::int32_t>>();
        // 重组织命令
        for (std::int32_t i = 1; i < splited_command.size(); i++)
        {
            // 辅助获取参数数值
            static std::int32_t assist_arg = 0;
            // --start或-s选项对应的参数值
            static std::int32_t start_arg = 0;
            // --end或-e选项对应的参数值
            static std::int32_t end_arg = 0;
            // --num或-n选项对应的参数值
            static std::int32_t num_arg = 0;
            // 是否有开始参数
            static bool if_start = false;
            // 是否有结束参数
            static bool if_end = false;
            // 是否有数量参数
            static bool if_num = false;
            // 辅助获取-s、-e、-n参数组
            static std::vector<std::int32_t> assist_args = std::vector<std::int32_t>(3, -1);
            // 当前是选项
            if (if_option)
            {
                // 保存当前值
                cur_option = splited_command[i];
                // 转短选项
                if (long_option_to_short_option.count(cur_option))
                {
                    cur_option = long_option_to_short_option[cur_option];
                }
                // option_arg_count中存在短选项，则表示cur_option可用
                if (option_arg_count.count(cur_option))
                {
                    // 当前选项所需的参数数量
                    arg_count = option_arg_count[cur_option];
                    // 参数数量不为0，则下一步需要转到解析参数的分支中
                    if (arg_count != 0)if_option = false;
                    else
                    {
                        // 获取选项编号
                        std::int32_t option_id_no_arg = option_id[cur_option];
                        // 读写器
                        static textfilerw::TextFileReaderAndWriter tfrw_for_history = textfilerw::TextFileReaderAndWriter();
                        // 辅助重读命令历史记录
                        std::vector<std::string> assist = std::vector<std::string>();
                        // assist的索引
                        std::int32_t j = 0;
                        switch (option_id_no_arg)
                        {
                        case 0:
                            // 重读命令历史记录
                            mysh::mysh_history_commands.clear();
                            assist = tfrw_for_history.read(mysh::mysh_history_file_name);
                            j = assist.size() > mysh::mysh_history_max_size ? assist.size() - mysh::mysh_history_max_size : 0;
                            for (; j < assist.size(); j++)
                            {
                                mysh::mysh_history_commands.push_back(assist[j]);
                            }
                            mysh::mysh_history_index = mysh::mysh_history_commands.size();
                            std::cerr << "\033[32m" << "读取历史记录成功" << "\033[0m" << std::endl;
                            break;
                        case 1:
                            // 覆写命令历史记录
                            tfrw_for_history.write(mysh::join(mysh::mysh_history_commands), mysh::mysh_history_file_name);
                            std::cerr << "\033[32m" << "写入历史记录成功" << "\033[0m" << std::endl;
                            break;
                        case 2:
                            // 清空命令历史记录
                            mysh::mysh_history_commands.clear();
                            tfrw_for_history.write("", mysh::mysh_history_file_name);
                            mysh::mysh_history_index = mysh::mysh_history_commands.size();
                            std::cerr << "\033[32m" << "清除历史记录成功" << "\033[0m" << std::endl;
                            break;
                        }
                    }
                }
                else
                {
                    // 当前splited_command值不是选项
                    if (cur_option[0] != '-')
                    {
                        std::cerr << "\033[31m" << "上一选项的参数过多或当前参数无对应选项, 可通过\"history --help\"查看帮助文档" << "\033[0m" << std::endl;
                    }
                    // 当前splited_command值是--help
                    else if (cur_option == "--help")
                    {
                        std::cerr << "\033[31m" << "选项" << cur_option << "仅可通过\"history --help\"使用" << "\033[0m" << std::endl;
                    }
                    // 当前splited_command是个选项但不是可用选项
                    else
                    {
                        std::cerr << "\033[31m" << "目前尚不存在" << cur_option << "选项, 可通过\"history --help\"查看帮助文档" << "\033[0m" << std::endl;
                    }
                }
            }
            // 当前是参数
            else
            {
                // 参数所需数量减一
                arg_count--;
                // 尝试获取参数数值
                try
                {
                    assist_arg = std::stoi(splited_command[i]);
                }
                catch(const std::exception& e)
                {
                    std::cerr << "\033[31m" << "选项" << cur_option << "的第" << option_arg_count[cur_option] - arg_count << "个参数发生错误，请检查" << std::endl;
                    continue;
                }
                // 参数所需数量减为0
                if (arg_count == 0)
                {
                    // 下一个splited_command值应该是选项
                    if_option = true;
                    // 当前选项id
                    std::int32_t option_id_arg = option_id[cur_option];
                    switch (option_id_arg)
                    {
                    case 3:
                        // 展示命令历史记录的展示起点
                        // 原本已有start对应的值，则表示上一组展示区间已解析结束，则保存上一组的值
                        if (if_start)
                        {
                            if_end = false;
                            if_num = false;
                            args.push_back(assist_args);
                            assist_args[0] = assist_args[1] = assist_args[2] = -1;
                        }
                        // 保存start对应的值
                        if_start = true;
                        assist_args[0] = assist_arg;
                        break;
                    case 4:
                        // 展示命令历史记录的展示终点
                        // 原本已有end对应的值，则表示上一组展示区间已解析结束，则保存上一组的值
                        if (if_end)
                        {
                            if_start = false;
                            if_num = false;
                            args.push_back(assist_args);
                            assist_args[0] = assist_args[1] = assist_args[2] = -1;
                        }
                        // 保存end对应的值
                        if_end = true;
                        assist_args[1] = assist_arg;
                        break;
                    case 5:
                        // 展示命令历史记录的展示数量
                        // 原本已有num对应的值，则表示上一组展示区间已解析结束，则保存上一组的值
                        if (if_num)
                        {
                            if_start = false;
                            if_end = false;
                            args.push_back(assist_args);
                            assist_args[0] = assist_args[1] = assist_args[2] = -1;
                        }
                        // 保存num对应的值
                        if_num = true;
                        assist_args[2] = assist_arg;
                        break;
                    }
                }
            }
            // 若有为保存的展示区间信息，则保存
            if (i == splited_command.size() - 1 && (if_start || if_end || if_num))
            {
                if_start = if_end = if_num = false;
                args.push_back(assist_args);
                assist_args[0] = assist_args[1] = assist_args[2] = -1;
            }
        }
        // 命令历史记录数量
        std::size_t n = mysh::mysh_history_commands.size();
        if (n == 0)
        {
            std::cerr << "\033[32m" << "当前无历史记录" << "\033[0m" << std::endl;
            return;
        }
        // 逐步展示每个展示区间内的命令历史记录
        for (std::int32_t i = 0; i < args.size(); i++)
        {
            // 起点
            std::int32_t start = args[i][0];
            // 终点
            std::int32_t end = args[i][1];
            // 数量
            std::int32_t num = args[i][2];
            // 保证start大于等于0
            start = start >= 0 ? start : 0;
            // 保证start小于等于n - 1
            start = start <= n - 1 ? start : n - 1;
            // 保证end小于等于n - 1
            end = end <= n - 1 ? end : n - 1;
            // 保证end大于start
            end = end > start ? end : start + 1;
            // 若为指定num，则num为start到end间的数量
            if (num == -1) num = end - start;
            // 保证num小于等于起点到终点间的数量
            num = num <= (end - start) ? num : (end - start);
            // 展示
            std::cerr << "\033[32m" << "从索引" << start << "到索引" << end << "间的前" << num << "个历史记录为：" << "\033[0m" << std::endl;
            for (std::int32_t j = start; j < start + num; j++)
            {
                std::cerr << mysh::mysh_history_commands[j] << std::endl;
                if (!isatty(STDOUT_FILENO))
                {
                    std::cout << mysh::mysh_history_commands[j] << std::endl;
                }
            }
        }
    }
}

// 内部命令type
void myType(const std::vector<std::string>& splited_command)
{
    // 光输入type不执行任何操作
    if (splited_command.size() < 2)
    {
        std::cerr << "\033[31m" << "请输入需要查看类型的命令，可通过\"type --help\"查看帮助文档" << "\033[0m" << std::endl;
    }
    // 帮助文档
    else if (splited_command.size() == 2 && splited_command[1] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "查看命令的类型，共有三种命令: 内部命令(mysh直接执行)、外部命令(由存储在~/my-shell/bin中的可执行文件执行)、系统命令(除前两种命令外的其他命令)" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "type [参数]..." << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "由大括号括起来的字符串" << std::endl;
        std::cerr << "    " << "指定需要查看类型的命令" << std::endl;
    }
    // 带参数的type命令
    else
    {
        // 逐个解析参数并向用户报告信息
        for (std::int32_t i = 1; i < splited_command.size(); i++)
        {
            // 合法的参数应该是被{}括起来的非空字符串
            if (splited_command[i].size() <= 2 || splited_command[i][0] != '{' || splited_command[i].back() != '}')
            {
                std::cerr << "\033[31m" << "参数\"" << splited_command[i] << "\"错误，可通过\"type --help查看帮助文档\"" << "\033[0m" << std::endl;
                continue;
            }
            // 去除大括号
            std::string cur_arg = splited_command[i];
            cur_arg.pop_back();
            cur_arg.erase(0, 1);
            // 判断是否为内部命令
            if (mysh::internal_commands.count(cur_arg))
            {
                std::cerr << "\033[33m" << cur_arg << "为内部命令" << "\033[0m" << std::endl;
            }
            // 判断是否为外部命令
            else if(mysh::external_commands.count(cur_arg))
            {
                std::cerr << "\033[34m" << cur_arg << "为外部命令" << "\033[0m" << std::endl;
            }
            // 非内部且非外部则表示可能为系统命令
            else
            {
                std::cerr << "\033[35m" << cur_arg << "可能为系统命令" << "\033[0m" << std::endl;
            }
        }
    }
}

// 刷新资源
void refreshResource()
{
    // 刷新当前路径的资源管理器的资源
    mysh::resource_manager->clearCurFiles();
    mysh::resource_manager->findFiles();
    // 刷新所有外部命令并创建外部命令字典树
    if (!mysh::external_commands.empty())
    {
        mysh::external_commands.clear();
    }
    if (mysh::external_commands_trie != nullptr)
    {
        delete mysh::external_commands_trie;
        mysh::external_commands_trie = new myds::Trie();
    }
    std::vector<std::string> external_commands_array = mysh::ResourceManager::createFilesArrayFromRootPath(mysh::external_commands_path);
    for (const std::string& external_command : external_commands_array)
    {
        mysh::external_commands.insert(external_command);
        mysh::external_commands_trie->insert(external_command);
    }
    // 刷新所有可能的系统命令的字典树
    mysh::system_commands_tries.clear();
    for (const std::string& system_commands_path : mysh::system_commands_paths)
    {
        std::vector<std::string> system_commands_array = mysh::ResourceManager::createFilesArrayFromRootPath(system_commands_path);
        myds::Trie* cur_system_trie = new myds::Trie();
        for (const std::string& system_command : system_commands_array)
        {
            cur_system_trie->insert(system_command);
        }
        mysh::system_commands_tries.push_back(cur_system_trie);
    }
}

// 刷新打印信息
void refreshInfo()
{
    // 获取用户信息
    mysh::cur_uid = getuid();
    mysh::cur_user_info = getpwuid(mysh::cur_uid);
    // 获取主机名
    char host_name[256] = {0};
    gethostname(host_name, 256);
    mysh::cur_host_name = std::string(host_name);
}

// refresh
void myRefresh(const std::vector<std::string>& splited_command)
{
    // 默认刷新资源
    if (splited_command.size() < 2)
    {
        mysh::refreshResource();
        std::cerr << "\033[32m" << "已刷新资源" << "\033[0m" << std::endl;
    }
    // 帮助文档
    else if (splited_command.size() == 2 && splited_command[1] == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "刷新资源、用户信息、主机信息" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "refresh [选项]" << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "  " << "-r  --resource" << std::endl;
        std::cerr << "    " << "刷新资源(默认选项)" << std::endl;
        std::cerr << "  " << "-i  --info" << std::endl;
        std::cerr << "    " << "刷新用户、主机信息" << std::endl;
    }
    // refresh带1个选项
    else if (splited_command.size() == 2)
    {
        // 刷新资源
        if (splited_command[1] == "-r" || splited_command[1] == "--resource")
        {
            mysh::refreshResource();
            std::cerr << "\033[32m" << "已刷新资源" << "\033[0m" << std::endl;
        }
        // 刷新用户、主机信息
        else if (splited_command[1] == "-i" || splited_command[1] == "--info")
        {
            mysh::refreshInfo();
            std::cerr << "\033[32m" << "已刷新用户、主机信息" << "\033[0m" << std::endl;
        }
        // 不可用选项
        else
        {
            std::cerr << "\033[31m" << splited_command[1] << "不是可用选项，可通过\"refresh --help\"查看帮助文档" << "\033[0m" << std::endl;
        }
    }
    // 命令过长
    else
    {
        std::cerr << "\033[31m" << "当前输入的refresh命令过长，可通过\"refresh --help\"查看帮助文档" << "\033[0m" << std::endl;
    }
}

// yeq
void yourYeq(const std::vector<std::string>& splited_command)
{
    std::cerr << "\033[31m" << "I have told you" << "\033[0m" << std::endl;
}

// help
void myHelp(const std::vector<std::string>& splited_command)
{
    std::cerr << "\033[32m" << "\n<<<欢迎使用mysh!>>>" << "\033[0m"
    << "\033[34m" << "\n内部命令: " << "\033[0m"
    << "\033[36m" << "\n1. exit [退出 mysh]\n   用法: exit [选项|参数]" << "\033[0m"
    << "\033[36m" << "\n2. change-skip [修改跳过字符]\n   用法: change-skip [参数]" << "\033[0m"
    << "\033[36m" << "\n3. ls [显示当前目录下的文件和文件夹]\n   用法: ls [[选项] [参数]...]..." << "\033[0m"
    << "\033[36m" << "\n4. cd [更改当前工作目录]\n   用法: cd [目标目录]" << "\033[0m"
    << "\033[36m" << "\n5. alias [展示或删除别名(或变量)]\n   用法: alias <选项|子命令>" << "\033[0m"
    << "\033[36m" << "\n6. history [显示最近使用的命令历史]\n   用法: history [选项]...[参数]..." << "\033[0m"
    << "\033[36m" << "\n7. type [显示命令类型]\n   用法: type [参数]..." << "\033[0m"
    << "\033[36m" << "\n8. refresh [刷新]\n   用法: refresh [选项]" << "\033[0m"
    << "\033[36m" << "\n9. yeq [执行你的Yeq]\n   用法: yeq" << "\033[0m"
    << std::endl;
}

// sh
void mySh(const std::vector<std::string>& splited_command)
{
    textfilerw::TextFileReaderAndWriter tfrw = textfilerw::TextFileReaderAndWriter();
    std::vector<mysh::Word> ans = std::vector<mysh::Word>();
    std::vector<std::shared_ptr<mysh::GrammarNode>> grammar_ans = std::vector<std::shared_ptr<mysh::GrammarNode>>();
    try
    {
        std::cerr << "\033[32m" << "开始词法分析..." << "\033[0m" << std::endl;
        ans = mysh::MyShellLexicalAnalyzer::analyze(tfrw.read(splited_command[1]), true);
    }
    catch (const std::exception& e)
    {
        std::cerr << "\033[31m" << "读取文件时出现错误: " << e.what() << "\033[0m" << std::endl;
        return;
    }
    try
    {
        std::cerr << "\033[32m" << "开始语法分析..." << "\033[0m" << std::endl;
        grammar_ans = mysh::MyShellParser::parse(ans);
    }
    catch(const mysh::GrammarException& ge)
    {
        std::cerr << "\033[31m" << "语法分析出现错误: " << ge.what() << "\033[0m" << std::endl;
        return;
    }
    mysh::MyShellLexicalAnalyzer::printAnalyzeMessage(ans);
    mysh::MyShellParser::printParseMessage(grammar_ans);
    try
    {
        std::cerr << "\033[32m" << "开始执行..." << "\033[0m" << std::endl;
        mysh::MyShellScriptExecutor::executeScript(grammar_ans);
    }
    catch(const mysh::ExecutorException& ee)
    {
        std::cerr << "\033[31m" << "执行出现错误: " << ee.what() << "\033[0m" << std::endl;
        return;
    }
}
MY_SHELL_NAMESPACE_END